package main

import "fmt"

/*
给定一个字符串 s ，请你找出其中不含有重复字符的 最长子串 的长度。
示例1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc"，所以其长度为 3。

示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b"，所以其长度为 1。

示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是"wke"，所以其长度为 3。
请注意，你的答案必须是 子串 的长度，"pwke"是一个子序列，不是子串。

提示：
0 <= s.length <= 5 * 104
s由英文字母、数字、符号和空格组成

来源：力扣（LeetCode）
链接：https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
*/

// 滑动窗口
func lengthOfLongestSubstring(s string) int {
	r, l, re, ind, tmp, ok := 0, 0, 0, 0, make(map[byte]int), false

	for r < len(s) {
		ind, ok = tmp[s[r]] // 判断获取的右侧字符是否在滑动窗口中
		if ok {
			for ; l <= ind; l++ {
				delete(tmp, s[l])
			}

		} else {
			if r-l+1 > re {
				re = r - l + 1
			}
			tmp[s[r]] = r
			r++
		}

	}
	return re
}

func main() {
	test1()
	test2()
	test3()
	test4()
	test5()
	test6()
	test7()
	test8()
}

func test1() {
	s := "tmmzuxt"
	fmt.Println(5 == lengthOfLongestSubstring(s))
}

func test2() {
	s := "bbbbb"
	fmt.Println(1 == lengthOfLongestSubstring(s))
}

func test3() {
	s := "pwwkew"
	fmt.Println(3 == lengthOfLongestSubstring(s))
}

func test4() {
	s := ""
	fmt.Println(0 == lengthOfLongestSubstring(s))
}

func test5() {
	s := " "
	fmt.Println(1 == lengthOfLongestSubstring(s))
}

func test6() {
	s := "ay"
	fmt.Println(2 == lengthOfLongestSubstring(s))
}

func test7() {
	s := "aab"
	fmt.Println(2 == lengthOfLongestSubstring(s))
}

// "qrsvbspk"

func test8() {
	s := "qrsvbspk"
	fmt.Println(5 == lengthOfLongestSubstring(s))
}
